package plaf.basic{
	
import com.adobe.serialization.json.JSON;

import flash.filters.BevelFilter;
import flash.filters.BlurFilter;
import flash.text.*;
import flash.utils.getTimer;

import org.aswing.*;
import org.aswing.Component;
import org.aswing.event.AWEvent;
import org.aswing.geom.IntDimension;
import org.aswing.geom.IntRectangle;
import org.aswing.graphics.Graphics2D;
import org.aswing.plaf.*;
import org.aswing.plaf.basic.BasicLabelUI;

/**
 * Label UI basic imp.
 * @author iiley
 * @private
 */
public class BasicHtmlLabelUI extends BasicLabelUI {
	
	public function BasicHtmlLabelUI(){
		super();
	}
 
    //--------------------------------------------------
    private static var viewRect:IntRectangle = new IntRectangle();
    private static var textRect:IntRectangle = new IntRectangle();
    private static var iconRect:IntRectangle = new IntRectangle();

    override public function paint(c:Component, g:Graphics2D, r:IntRectangle):void{
    	super.paint(c, g, r);
    	var b:JLabel = JLabel(c);
    	
    	viewRect.setRect(r);
    	
    	textRect.x = textRect.y = textRect.width = textRect.height = 0;
        iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0;
        // layout the text and icon
        var text:String = layoutCompoundLabel(c, 
            c.getFont(), b.getText(), getIconToLayout(), 
            b.getVerticalAlignment(), b.getHorizontalAlignment(),
            b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
            viewRect, iconRect, textRect, 
	    	b.getText() == null ? 0 : b.getIconTextGap());
	   	
    	
    	paintIcon(b, g, iconRect);

trace('BasicHtmlLabelUI >' + text);
    	
        if (text != null && text != ""){
        	textField.visible = true;
			paintText(b, textRect, text);
            
        }else{
        	textField.htmlText = "";
        	textField.visible = false;
        }
        
        textField.selectable = b.isSelectable();
        textField.mouseEnabled = b.isSelectable();
    }
    
    /**
     * paint the text to specified button with specified bounds
     */
    override protected function paintText(b:JLabel, textRect:IntRectangle, text:String):void{
    	var font:ASFont = b.getFont();
        trace('BasicHtmlLabelUI >' + text);

//		if(textField.htmlText != text){
			textField.htmlText = text;
//		}
//		if(!b.isFontValidated()){
//			AsWingUtils.applyTextFont(textField, font);
//			b.setFontValidated(true);
//		}
    	AsWingUtils.applyTextColor(textField, b.getForeground());
		textField.x = textRect.x;
		textField.y = textRect.y;
    	if(!b.isEnabled()){
    		b.filters = [new BlurFilter(2, 2, 2)];
    	}else{
    		b.filters = null;
    	}
    	textField.filters = label.getTextFilters();
        trace('BasicHtmlLabelUI >' + textField.htmlText);
    }
    /**
     * Compute and return the location of the icons origin, the
     * location of origin of the text baseline, and a possibly clipped
     * version of the compound labels string.  Locations are computed
     * relative to the viewR rectangle.
     */
    protected function layoutCompoundLabel(
        c:Component, 
        f:ASFont, 
        text:String,
        icon:Icon,
        verticalAlignment:int,
        horizontalAlignment:int,
        verticalTextPosition:int,
        horizontalTextPosition:int,
        viewR:IntRectangle,
        iconR:IntRectangle,
        textR:IntRectangle,
        textIconGap:int):String
    {
//        var text:String = extractStringFromHtml(html);
        if (icon != null) {
            iconR.width = icon.getIconWidth(c);
            iconR.height = icon.getIconHeight(c);
        }else {
            iconR.width = iconR.height = 0;
        }
        
        var textIsEmpty:Boolean = (text==null || text=="");
        if(textIsEmpty){
            textR.width = textR.height = 0;
        }else{
            var textS:IntDimension = inter_computeStringSize(f, text);
            textR.width = textS.width;
            textR.height = textS.height;
        }
        
        /* Unless both text and icon are non-null, we effectively ignore
        * the value of textIconGap.  The code that follows uses the
        * value of gap instead of textIconGap.
        */
        
        var gap:Number = (textIsEmpty || (icon == null)) ? 0 : textIconGap;
        
        if(!textIsEmpty){
            
            /* If the label text string is too wide to fit within the available
            * space "..." and as many characters as will fit will be
            * displayed instead.
            */
            var availTextWidth:Number;
            
            if (horizontalTextPosition == AsWingUtils.CENTER) {
                availTextWidth = viewR.width;
            }else {
                availTextWidth = viewR.width - (iconR.width + gap);
            }
            
            if (textR.width > availTextWidth) {
                text = layoutTextWidth(text, textR, availTextWidth, f);
            }
        }
        
        /* Compute textR.x,y given the verticalTextPosition and
        * horizontalTextPosition properties
        */
        
        if (verticalTextPosition == AsWingUtils.TOP) {
            if (horizontalTextPosition != AsWingUtils.CENTER) {
                textR.y = 0;
            }else {
                textR.y = -(textR.height + gap);
            }
        }else if (verticalTextPosition == AsWingUtils.CENTER) {
            textR.y = (iconR.height / 2) - (textR.height / 2);
        }else { // (verticalTextPosition == BOTTOM)
            if (horizontalTextPosition != AsWingUtils.CENTER) {
                textR.y = iconR.height - textR.height;
            }else {
                textR.y = (iconR.height + gap);
            }
        }
        
        if (horizontalTextPosition == AsWingUtils.LEFT) {
            textR.x = -(textR.width + gap);
        }else if (horizontalTextPosition == AsWingUtils.CENTER) {
            textR.x = (iconR.width / 2) - (textR.width / 2);
        }else { // (horizontalTextPosition == RIGHT)
            textR.x = (iconR.width + gap);
        }
        
        
        //trace("textR : " + textR);
        //trace("iconR : " + iconR);    
        //trace("viewR : " + viewR);    
        
        /* labelR is the rectangle that contains iconR and textR.
        * Move it to its proper position given the labelAlignment
        * properties.
        *
        * To avoid actually allocating a Rectangle, Rectangle.union
        * has been inlined below.
        */
        var labelR_x:Number = Math.min(iconR.x, textR.x);
        var labelR_width:Number = Math.max(iconR.x + iconR.width, textR.x + textR.width) - labelR_x;
        var labelR_y:Number = Math.min(iconR.y, textR.y);
        var labelR_height:Number = Math.max(iconR.y + iconR.height, textR.y + textR.height) - labelR_y;
        
        //trace("labelR_x : " + labelR_x);
        //trace("labelR_width : " + labelR_width);  
        //trace("labelR_y : " + labelR_y);
        //trace("labelR_height : " + labelR_height);        
        
        var dx:Number = 0;
        var dy:Number = 0;
        
        if (verticalAlignment == AsWingUtils.TOP) {
            dy = viewR.y - labelR_y;
        }
        else if (verticalAlignment == AsWingUtils.CENTER) {
            dy = (viewR.y + (viewR.height/2)) - (labelR_y + (labelR_height/2));
        }
        else { // (verticalAlignment == BOTTOM)
            dy = (viewR.y + viewR.height) - (labelR_y + labelR_height);
        }
        
        if (horizontalAlignment == AsWingUtils.LEFT) {
            dx = viewR.x - labelR_x;
        }
        else if (horizontalAlignment == AsWingUtils.RIGHT) {
            dx = (viewR.x + viewR.width) - (labelR_x + labelR_width);
        }
        else { // (horizontalAlignment == CENTER)
            dx = (viewR.x + (viewR.width/2)) - (labelR_x + (labelR_width/2));
        }
        
        /* Translate textR and glypyR by dx,dy.
        */
        
        //trace("dx : " + dx);
        //trace("dy : " + dy);  
        
        textR.x += dx;
        textR.y += dy;
        
        iconR.x += dx;
        iconR.y += dy;
        
        //trace("tf = " + tf);
        
        //trace("textR : " + textR);
        //trace("iconR : " + iconR);        
        
        trace('layoutCompoundLabel >' + iconR.x + ' ' + iconR.y + ' ' + iconR.width + ' ' + iconR.height);
        trace('layoutCompoundLabel >' + textR.x + ' ' + textR.y + ' ' + textR.width + ' ' + textR.height);
        return text;
//        return html;
    }
    
    private static function extractStringFromHtml(html:String):String {
        var open:Boolean = false;
        var text:String = '';
        if (html) {
            for (var i:int = 0; i < html.length; ++i) {
                if (html.charAt(i) == '<') {
                    open = true;
                } else if (html.charAt(i) == '>') {
                    open = false;
                } else if (!open) text = text.concat(html.charAt(i));
            }
        }
        trace('extractStringFromHtml >' + text);
        return text;
    }
    private static var TEXT_FIELD:TextField = new TextField();
    private static var TEXT_FONT:ASFont = null;
    private static function inter_computeStringWidth(font:ASFont, str:String):Number{
//        var TEXT_FIELD:TextField = new TextField();
        TEXT_FIELD.htmlText = str;
//        if(TEXT_FONT != font){
//            font.apply(TEXT_FIELD);
//            TEXT_FONT = font;
//        }
        trace('inter_computeStringWidth >' + str + ' ' + TEXT_FIELD.width);
        return TEXT_FIELD.width;
    }

    private static function layoutTextWidth(text:String, textR:IntRectangle, availTextWidth:Number, font:ASFont):String{
        if (textR.width <= availTextWidth) {
            return text;
        }
        var clipString:String = "...";
        var totalWidth:int = Math.round(inter_computeStringWidth(font, clipString));
        if(totalWidth > availTextWidth){
            totalWidth = Math.round(inter_computeStringWidth(font, ".."));
            if(totalWidth > availTextWidth){
                text = ".";
                textR.width = Math.round(inter_computeStringWidth(font, "."));
                if(textR.width > availTextWidth){
                    textR.width = 0;
                    text = "";
                }
            }else{
                text = "..";
                textR.width = totalWidth;
            }
            return text;
        }else{
            var lastWidth:Number = totalWidth;
            
            
            //begin binary search
            var num:int = text.length;
            var li:int = 0; //binary search of left index 
            var ri:int = num; //binary search of right index
            
            while(li<ri){
                var i:int = li + (ri - li)/2;
                var subText:String = text.substring(0, i);
                var length:int = Math.ceil(lastWidth + inter_computeStringWidth(font, subText));
                
                if((li == i - 1) && li>0){
                    if(length > availTextWidth){
                        subText = text.substring(0, li);
                        textR.width = Math.ceil(lastWidth + inter_computeStringWidth(font, text.substring(0, li)));
                    }else{
                        textR.width = length;
                    }
                    return subText + clipString;
                }else if(i <= 1){
                    if(length <= availTextWidth){
                        textR.width = length;
                        return subText + clipString;
                    }else{
                        textR.width = lastWidth;
                        return clipString;
                    }
                }
                
                if(length < availTextWidth){
                    li = i;
                }else if(length > availTextWidth){
                    ri = i;
                }else{
                    text = subText + clipString;
                    textR.width = length;
                    return text;
                }
            }
            //end binary search
            textR.width = lastWidth;
            return "";
        }
    } 
    
    private static function inter_computeStringSize(font:ASFont, str:String):IntDimension{
        TEXT_FIELD.htmlText = str;
//        if(TEXT_FONT != font){
//            font.apply(TEXT_FIELD);
//            TEXT_FONT = font;
//        }
        trace('inter_computeStringSize >' + str + ' ' + TEXT_FIELD.width + ' ' + TEXT_FIELD.height);
        return new IntDimension(Math.ceil(TEXT_FIELD.width), Math.ceil(TEXT_FIELD.height));
    }

}


}
